#include "FlashOS.H"        // FlashOS Structures
#include "W25Q128_sim.h"
#include "stm32f7xx.h"
#include "IP_PLL.h"




/**
 * @brief STM32时钟初始化
 * @return 无
 */
void SystemClock_Config(void){

  RCC->APB1ENR|=RCC_APB1ENR_PWREN;
  RCC->APB2ENR|=RCC_APB2ENR_SYSCFGEN;
	
  PWR->CR1=(PWR->CR1&(~PWR_CR1_VOS_Msk))|(0x3<<PWR_CR1_VOS_Pos);//Scale1
  // while((PWR->CSR1&PWR_CSR1_VOSRDY)!=PWR_CSR1_VOSRDY){
  //   //等待电压等级就绪
  // }

  if((RCC->CFGR&RCC_CFGR_SWS_Msk)!=RCC_CFGR_SWS_HSI){
    //如果系统时钟源不为HSI

    if(RCC->CR&RCC_CR_HSION){
      RCC->CR&=(~RCC_CR_HSION);
    }
    while(RCC->CR&RCC_CR_HSIRDY){
      //等待HSI关闭
    }

    if((RCC->CR&RCC_CR_HSION)!=RCC_CR_HSION){
      RCC->CR|=RCC_CR_HSION;//使能HSI
      while(!(RCC->CR&RCC_CR_HSIRDY)){
        //等待HSI稳定
      }
    }

    RCC->CFGR=(RCC->CFGR&(~RCC_CFGR_SW_Msk))|RCC_CFGR_SW_HSI;
    while((RCC->CFGR&RCC_CFGR_SWS_Msk)!=RCC_CFGR_SWS_HSI){
      //等待时钟切换完成
    }
  }
  //此时系统时钟变为HSI

  //如果HSE未使能
  if(!(RCC->CR&RCC_CR_HSEON)){
    RCC->CR|=RCC_CR_HSEON;
  }
  while(!(RCC->CR&RCC_CR_HSERDY)){
    //等待HSE稳定
  }


  PWR->CR1|=PWR_CR1_ODEN;
  while((PWR->CSR1&PWR_CSR1_ODRDY)!=PWR_CSR1_ODRDY){
    //等待OverDrive准备好
  }
  
  PWR->CR1|=PWR_CR1_ODSWEN;
  while((PWR->CSR1&PWR_CSR1_ODSWRDY)!=PWR_CSR1_ODSWRDY){
    //等待OverDrive准备好
  }


  //关闭所有的PLL
  PLL_SetStatus(0);
  PLLI2S_SetStatus(0);
  PLLSAI_SetStatus(0);

  //PLL时钟选择为HSI
  RCC->PLLCFGR=(RCC->PLLCFGR&(~RCC_PLLCFGR_PLLSRC_Msk))|RCC_PLLCFGR_PLLSRC_HSI;

  PLL_SetDIV(16,432,2,2,2);
  //PLLI2S_SetDIV(192,2,2,2,1);
  //PLLSAI_SetDIV(192,2,2,2,1);

  PLL_SetStatus(1);
  //PLLI2S_SetStatus(0);
  //PLLSAI_SetStatus(0);

  //设置分频
  RCC->CFGR=(RCC->CFGR&(~(RCC_CFGR_HPRE_Msk|RCC_CFGR_PPRE1_Msk|RCC_CFGR_PPRE2_Msk)))
  |RCC_CFGR_HPRE_DIV1|RCC_CFGR_PPRE1_DIV2|RCC_CFGR_PPRE2_DIV1;

	//设置Flash延时
  FLASH->ACR=(FLASH->ACR&(~FLASH_ACR_LATENCY_Msk))|FLASH_ACR_LATENCY_7WS;

  //切换系统时钟到PLL
  RCC->CFGR = (RCC->CFGR&(~RCC_CFGR_SW_Msk))|RCC_CFGR_SW_PLL;
  while((RCC_CFGR_SWS_Msk & RCC->CFGR) != RCC_CFGR_SWS_PLL){
    //等待切换完毕
  }

  //更新SystemCoreClock
  //SystemCoreClockUpdate();
  //SystemCoreClock=96000000U;


  //PeripheralClkSelConfig();
  
}




#define Buffer_Verify_Size 	(1*1024)
unsigned char Buffer_Verify[Buffer_Verify_Size];

unsigned long BaseAddress;

/*
 *  Initialize Flash Programming Functions
 *    Parameter:      adr:  Device Base Address
 *                    clk:  Clock Frequency (Hz)
 *                    fnc:  Function Code (1 - Erase, 2 - Program, 3 - Verify)
 *    Return Value:   0 - OK,  1 - Failed
 */
int Init (unsigned long adr, unsigned long clk, unsigned long fnc) {

	BaseAddress=adr;

  //SystemClock_Config();
	W25Q_sim_Init();

	switch(fnc){
		case 1:
			
		
			break;
		case 2:
			break;
		case 3:
			break;
	}
	
	
  return (0);                                  // Finished without Errors
}


/*
 *  De-Initialize Flash Programming Functions
 *    Parameter:      fnc:  Function Code (1 - Erase, 2 - Program, 3 - Verify)
 *    Return Value:   0 - OK,  1 - Failed
 */
int UnInit (unsigned long fnc) {
	
	
	
  return (0);                                  // Finished without Errors
}


/*
 *  Erase complete Flash Memory
 *    Return Value:   0 - OK,  1 - Failed
 */

int EraseChip (void) {
	
	W25Q_sim_ChipErase();
  
  return (0);                                  // Finished without Errors
}


/*
 *  Erase Sector in Flash Memory
 *    Parameter:      adr:  Sector Address
 *    Return Value:   0 - OK,  1 - Failed
 */

int EraseSector (unsigned long adr) {
	
	W25Q_sim_64KBErase(adr-BaseAddress);
	
  return (0);                                  // Finished without Errors
}


/*
 *  Program Page in Flash Memory
 *    Parameter:      adr:  Page Start Address
 *                    sz:   Page Size
 *                    buf:  Page Data
 *    Return Value:   0 - OK,  1 - Failed
 */

int ProgramPage (unsigned long adr, unsigned long sz, unsigned char *buf) {
	
	
	while(sz>256){
		W25Q_sim_PageProgram(adr-BaseAddress,buf,256);
		buf+=256;
		sz-=256;
		adr+=256;
	}
	if(sz){
		W25Q_sim_PageProgram(adr-BaseAddress,buf,sz);
	}
  
  return (0);                                  // Finished without Errors
}




int BlankCheck(unsigned long adr,unsigned long sz,unsigned char pat){
 
	
	return (1);//固定返回未擦除
}
 

 /*  
 *  Verify Flash Contents
 *    Parameter:      adr:  Start Address
 *                    sz:   Size (in bytes)
 *                    buf:  Data
 *    Return Value:   (adr+sz) - OK, Failed Address
 */
unsigned long Verify(unsigned long adr,unsigned long sz,unsigned char *buf){
	unsigned int offset;
	
	while(sz>Buffer_Verify_Size){
		W25Q_sim_ReadData(adr-BaseAddress,Buffer_Verify,Buffer_Verify_Size);
		
		offset=0;
		while(offset<Buffer_Verify_Size){
			if(Buffer_Verify[offset]!=*buf){
				return adr+offset;//return Err
			}
			buf++;
			offset++;
		}
		
		adr+=Buffer_Verify_Size;
		sz-=Buffer_Verify_Size;
	}
	if(sz){
		W25Q_sim_ReadData(adr-BaseAddress,Buffer_Verify,sz);
		
		offset=0;
		while(offset<sz){
			if(Buffer_Verify[offset]!=*buf){
				return adr+offset;//return Err
			}
			buf++;
			offset++;
		}
		
		adr+=sz;
	}
	
	return adr;
}

